
package ch.hearc.meteo.imp.reseau;

import java.io.FileInputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.util.Properties;

import javax.swing.JOptionPane;

import ch.hearc.meteo.imp.afficheur.real.AfficheurService;
import ch.hearc.meteo.imp.afficheur.real.JDialogPreferencesRemote;
import ch.hearc.meteo.imp.afficheur.real.JFrameStationMeteo;
import ch.hearc.meteo.spec.afficheur.AffichageOptions;
import ch.hearc.meteo.spec.afficheur.AfficheurFactory;
import ch.hearc.meteo.spec.afficheur.AfficheurService_I;
import ch.hearc.meteo.spec.reseau.AfficheurManager_I;
import ch.hearc.meteo.spec.reseau.AfficheurServiceWrapper;
import ch.hearc.meteo.spec.reseau.AfficheurServiceWrapper_I;
import ch.hearc.meteo.spec.reseau.MeteoServiceWrapper_I;

import com.bilat.tools.reseau.rmi.IdTools;
import com.bilat.tools.reseau.rmi.RmiTools;
import com.bilat.tools.reseau.rmi.RmiURL;

/**
 * <pre>
 * One instance only (Singleton) on PC-Central
 * RMI-Shared
 * </pre>
 */
public class AfficheurManager implements AfficheurManager_I
	{

	/*------------------------------------------------------------------*\
	|*							Constructeurs							*|
	\*------------------------------------------------------------------*/

	private AfficheurManager() throws RemoteException
		{
		server();
		}

	/*------------------------------------------------------------------*\
	|*							Methodes Public							*|
	\*------------------------------------------------------------------*/

	/**
	 * Remote use
	 */
	@Override
	public RmiURL createRemoteAfficheurService(AffichageOptions affichageOptions, RmiURL meteoServiceRmiURL) throws RemoteException
		{
		MeteoServiceWrapper_I meteoServiceRemote = null;
			// client
			{
			meteoServiceRemote = (MeteoServiceWrapper_I)RmiTools.connectionRemoteObjectBloquant(meteoServiceRmiURL);
			}

			// server
			{
			AfficheurService_I afficheurService = createAfficheurService(affichageOptions, meteoServiceRemote);
			AfficheurServiceWrapper_I afficheurServiceWrapper = new AfficheurServiceWrapper(afficheurService);

			launchRmiLookup(meteoServiceRmiURL, meteoServiceRemote, afficheurService);

			JFrameStationMeteo.getInstance().addMeteoServiceWrapper(meteoServiceRemote, (AfficheurService)afficheurService);

			RmiURL afficheurServicermiURL = rmiUrl();

			RmiTools.shareObject(afficheurServiceWrapper, afficheurServicermiURL);
			return afficheurServicermiURL; // Retourner le RMI-ID pour une connection distante sur le serveur d'affichage
			}
		}

	/*------------------------------*\
	|*			  Static			*|
	\*------------------------------*/

	public static synchronized AfficheurManager_I getInstance() throws RemoteException
		{
		if (INSTANCE == null)
			{
			INSTANCE = new AfficheurManager();
			}

		return INSTANCE;
		}

	/*------------------------------------------------------------------*\
	|*							Methodes Private						*|
	\*------------------------------------------------------------------*/

	private AfficheurService_I createAfficheurService(AffichageOptions affichageOptions, MeteoServiceWrapper_I meteoServiceRemote)
		{
		return AfficheurFactory.create(affichageOptions, meteoServiceRemote);
		}

	private void server() throws RemoteException
		{
		rmiPort = 0;
		Properties p = new Properties();
		try
			{
			p.load(new FileInputStream(JDialogPreferencesRemote.PROPERTY_FILENAME));
			rmiPort = Integer.valueOf(p.getProperty(JDialogPreferencesRemote.SERVER_PORT_PROPERTY_NAME));
			}
		catch (Exception e)
			{
			// TODO Auto-generated catch block
			e.printStackTrace();
			}

		rmiURL = new RmiURL(ID_DISPLAY_MANAGER, rmiPort);
		RmiTools.shareObject(this, rmiURL);
		}

	private void launchRmiLookup(final RmiURL meteoServiceRmiURL, final MeteoServiceWrapper_I meteoServiceWrapper, final AfficheurService_I afficheurService)
		{
		Thread thread = new Thread(new Runnable()
			{
				@Override
				public void run()
					{
					boolean isFinish = false;
					while(!isFinish)
						{
						try
							{
							meteoServiceWrapper.remoteTest();
							}
						catch (Exception e)
							{
							JFrameStationMeteo.getInstance().removeMeteoServiceWrapper(meteoServiceWrapper, (AfficheurService)afficheurService);
							JOptionPane.showMessageDialog(null, "Une station météo ne répond plus", "Erreur", JOptionPane.ERROR_MESSAGE);
							isFinish = true;
							}

						try
							{
							Thread.sleep(RMI_LOOKUP_SLEEP_MS);
							}
						catch (InterruptedException e)
							{
							// TODO Auto-generated catch block
							e.printStackTrace();
							}
						}
					}
			});
		thread.start();

		}

	/*------------------------------*\
	|*			  Static			*|
	\*------------------------------*/

	/**
	 * Thread Safe
	 */
	private static RmiURL rmiUrl()
		{
		String id = IdTools.createID(PREFIXE);

		int rmiPort = 0;
		Properties p = new Properties();
		try
			{
			p.load(new FileInputStream(JDialogPreferencesRemote.PROPERTY_FILENAME));
			rmiPort = Integer.valueOf(p.getProperty(JDialogPreferencesRemote.SERVER_PORT_PROPERTY_NAME));
			}
		catch (Exception e)
			{
			// TODO Auto-generated catch block
			e.printStackTrace();
			}

		RmiURL rmiURL = null;

		try
			{
			rmiURL = new RmiURL(id, InetAddress.getLocalHost(), rmiPort);
			}
		catch (UnknownHostException e)
			{
			// TODO Auto-generated catch block
			e.printStackTrace();
			}

		return rmiURL;
		}

	/*------------------------------------------------------------------*\
	|*							Attributs Private						*|
	\*------------------------------------------------------------------*/

	/*------------------------------*\
	|*			  Static			*|
	\*------------------------------*/

	// Tools
	private static AfficheurManager_I INSTANCE = null;
	private int rmiPort;
	private RmiURL rmiURL;

	// Tools final
	private static final String PREFIXE = "AFFICHEUR_SERVICE";
	public static final String RMI_ID = PREFIXE;
	public static final String ID_DISPLAY_MANAGER = "AFFICHEUR_MANAGEUR";
	private static final int RMI_LOOKUP_SLEEP_MS = 500;

	}
